U ovom radu, zadatak je da se na osnovu informacija o vozilima u SAD pripremi skup na nacin da se dovoljno dobro istrenira model koji ce moci da predvidi cenu vozila na osnovu ostalih parametara sem cene. U daljem tekstu ce biti prvo objasnjen skup podataka, zatim modeli koji ce se koristiti a onda i prikaz konacnih rezultata, evaluacionih metrika i testiranja istreniranog modela.
U ovom koraku ce biti uvezene biblioteke potrebne za dalji rad
import numpy as np
import pandas as pd
import hvplot.pandas
import seaborn as sns
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error as MSE
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
Skup podataka nad kojim ce biti izvrsena analiza, predstavlja inforrmacije o automobilima.
Podaci su sa sledeceg linka: https://www.kaggle.com/datasets/deepcontractor/car-price-prediction-challenge?resource=download
data = pd.read_csv("./car_price_prediction.csv")
data.head()
| ID | Price | Levy | Manufacturer | Model | Prod. year | Category | Leather interior | Fuel type | Engine volume | Mileage | Cylinders | Gear box type | Drive wheels | Doors | Wheel | Color | Airbags | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 45654403 | 13328 | 1399 | LEXUS | RX 450 | 2010 | Jeep | Yes | Hybrid | 3.5 | 186005 km | 6.0 | Automatic | 4x4 | 04-May | Left wheel | Silver | 12 |
| 1 | 44731507 | 16621 | 1018 | CHEVROLET | Equinox | 2011 | Jeep | No | Petrol | 3 | 192000 km | 6.0 | Tiptronic | 4x4 | 04-May | Left wheel | Black | 8 |
| 2 | 45774419 | 8467 | - | HONDA | FIT | 2006 | Hatchback | No | Petrol | 1.3 | 200000 km | 4.0 | Variator | Front | 04-May | Right-hand drive | Black | 2 |
| 3 | 45769185 | 3607 | 862 | FORD | Escape | 2011 | Jeep | Yes | Hybrid | 2.5 | 168966 km | 4.0 | Automatic | 4x4 | 04-May | Left wheel | White | 0 |
| 4 | 45809263 | 11726 | 446 | HONDA | FIT | 2014 | Hatchback | Yes | Petrol | 1.3 | 91901 km | 4.0 | Automatic | Front | 04-May | Left wheel | Silver | 4 |
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 19237 entries, 0 to 19236 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 ID 19237 non-null int64 1 Price 19237 non-null int64 2 Levy 19237 non-null object 3 Manufacturer 19237 non-null object 4 Model 19237 non-null object 5 Prod. year 19237 non-null int64 6 Category 19237 non-null object 7 Leather interior 19237 non-null object 8 Fuel type 19237 non-null object 9 Engine volume 19237 non-null object 10 Mileage 19237 non-null object 11 Cylinders 19237 non-null float64 12 Gear box type 19237 non-null object 13 Drive wheels 19237 non-null object 14 Doors 19237 non-null object 15 Wheel 19237 non-null object 16 Color 19237 non-null object 17 Airbags 19237 non-null int64 dtypes: float64(1), int64(4), object(13) memory usage: 2.6+ MB
data.shape
(19237, 18)
U skupu imamo 19237 redova i 18 kolona
ID - identifikacioni broj automobila, numericka promenljiva
Price - cena automobila, numericka promenljiva
Levy - taksa za vozilo - osiguranje, string sa numerickim vrednostima
Manufacturer - marka automobila, nominalna
Model - model automobila, nominalna
Prod. year - godina proizvodnje, numericka
Category - karoserija, nominalna
Leaher interior - da li je kozni interijer, boolean - binarna
Fuel type - tip goriva, nominalna
Engine volume - zapremina motora, string sa numerickim vrednostima
Mileage - predjena kilometraza, numericka
Cylinders - broj cilindara, numericka
Gear box type - tip menjaca, nominalna
Drive wheels - tip pogona, nominalna
Doors - ova kolona treba da predstavlja broj vrata ali je format kolone los pa prikazuje datum
Wheel - strana volana, nominalna
Color - boja automobila, nominalna
Airbags - broj airbagova u automobilu, numericka
data.isnull().sum(axis=0)
ID 0 Price 0 Levy 0 Manufacturer 0 Model 0 Prod. year 0 Category 0 Leather interior 0 Fuel type 0 Engine volume 0 Mileage 0 Cylinders 0 Gear box type 0 Drive wheels 0 Doors 0 Wheel 0 Color 0 Airbags 0 dtype: int64
Nijedna kolona nema nedostajucih vrednosti, ali je bitno proveriti da li postoji prazan string ili crtica u nekoj koloni.
Kolona koja ima crtica, primecenih pri prikazivanju prvih pet kolona je levy, pa cemo ispitati podatke u njoj.
sum(data.Levy == "")
0
sum(data.Levy == "-")
5819
sum(data.Levy == "0")
0
Imamo 5819 redova sa "-", koje cemo zameniti nulom jer pretpostavka je da "-" znaci da automobil nema osiguranje.
data.Levy = data.Levy.replace('-',0)
Sledeca kolona je 'Doors' koju bi trebalo izmeniti da broj vrata ne bude datum, vec klasican broj u formatu 2-3.
data['Doors'] = data['Doors'].str.replace('02-Mar','2-3').replace('04-May','4-5')
Takodje imamo kolonu 'Mileage' koja sadrzi km. Vazno je izbaciti km deo i pretvoriti podatke u int
data['Mileage'] = data['Mileage'].str.replace('km', '')
data['Mileage'] = data['Mileage'].astype(int)
data['Levy']= data['Levy'].astype(int)
data["Engine volume"] = data["Engine volume"].str.replace('Turbo','')
data["Engine volume"] = data["Engine volume"].astype(float)
Zbog lakseg pristupanja kolonama kao i jasnijih imena, kolone ce biti preimenovane.
data = data.rename(columns={'Price':'price',
'Levy':'levy',
'Manufacturer':'manufacturer',
'Model':'model',
'Prod. year':'prod_year',
'Category':'category',
'Leather interior':'leather',
'Fuel type':'fuel' ,
'Engine volume':'engine_volume',
'Mileage':'mileage',
'Cylinders':'cylinders',
'Gear box type' : 'gearbox' ,
'Drive wheels': 'drivewheels' ,
'Doors': 'doors' ,
'Wheel':'wheel' ,
'Color':'color',
'Airbags':'airbags'})
data.duplicated().sum()
313
Imamo 313 duplikata koje cemo izbaciti
data.drop_duplicates(inplace=True)
U ovom koraku, bice vizuelno predstavljani medjusobni odnosi razlicitih promenljivih, sa akcentom na cenu.
Kako je glavni cilj pozabaviti se cenom i dobiti predikcije za cenu automobila, prvo ce biti prikazana distribucija cene i ukoliko postoje neke ekstremne vrednosti, bice otklonjene
data["price"].plot.box()
plt.xticks(rotation='vertical')
(array([1]), [Text(1, 0, 'price')])
Ovde vidimo da postoji nekoliko outliera, kojima cemo da se pozabavimo
data["price"].value_counts().sort_index()
1 2
3 15
6 6
9 1
19 1
..
297930 2
308906 1
627220 1
872946 1
26307500 1
Name: price, Length: 2315, dtype: int64
Vidimo da je to tri vrednosti koje su dosta vece od ostalih, 627220, 872946 i 26307500, pretpostavka je da je to samo par luksuznih automobila koji mogu uticati na kasnije predikcije i otklonicemo ih iz skupa.
Takodje uocavamo da imamo neke vrednosti koje su dosta male, istrazivanjem cene polovnih vozila u USA nije za ocekivati da vozila imaju cenu ispod 500 dolara sem ako su ostecena i nisu u voznom stanju.
Posto ne postoji informacija o tome da li je vozilo osteceno ili ne, uklonicemo vrednosti ispod 500$
(data['price'] < 500).value_counts()
False 17291 True 1633 Name: price, dtype: int64
data = data[data["price"] < 627220]
data = data[data["price"] >= 500]
data["price"].plot.box()
plt.xticks(rotation='vertical')
(array([1]), [Text(1, 0, 'price')])
Distribucija cene je sada dosta normalnija nego na prethodnoj slici.
sns.distplot(data['price'])
plt.legend(loc = 'best')
plt.title('Distribucija cene vozila ')
C:\Users\PC-Korisnik\anaconda3\lib\site-packages\seaborn\distributions.py:2619: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). warnings.warn(msg, FutureWarning) No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
Text(0.5, 1.0, 'Distribucija cene vozila ')
Najzastupljeniji su automobili sa cenom do 50000, sto je i realno ocekivati. Primetan je pad u broju automobila sa cenom od preko 25000 sto polako prelazi u skupocene i luksuzne automobile.
plt.figure(figsize = (15,7))
plt.title("Broj automobila po proizvodjacu")
plt1 = data.manufacturer.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Proizvodjac', ylabel = 'Broj')
plt.show()
Primecujemo da oko 20 proizvodjaca predstavlja najveci broj automobila u skupu, ostali proizvodjaci imaju zanemarljiv broj u odnosu na njih. Izdvajaju se Hyundai, Toyota i Mercedes.
plt.figure(figsize = (15,7))
plt.title("Broj automobila po karoseriji")
plt1 = data.category.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Karoserija', ylabel = 'Broj')
plt.show()
Najveci broj automobila je sedan ili jeep, dok pickup, kabriolet i limuzine predstavljaju veoma mali udeo. Ostale kategorije imaju priblizan broj automobila.
plt.figure(figsize = (15,7))
plt.title("Broj automobila po godini proizvodnje")
plt1 = data.prod_year.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Godina', ylabel = 'Broj')
plt.show()
U skupu se nalaze automobili koji su uglavnom proizvedeni nakon 1995. godine, dok najveci broj cine oni proizvodeni izmedju 2010.i 2015. godine
plt.figure(figsize=(15,7))
sns.histplot(binwidth=0.5, x="category", hue="fuel", data=data, stat="count", multiple="stack")
<AxesSubplot:xlabel='category', ylabel='Count'>
Jos jedna stvar koju zapazmo je da vrsta goriva zavisi od karoserije, pa je tako najvise hibrida u sedanu, hecbeku i dzipu dok skoro svi kupe automobili koriste benzin.
Posto smo gore primetili da je broj automobila starijih od 1990. godine zanemarljiv izbacicemo ih i prikazati informacije o automobilima proizvedenim nakon 1990. godine.
data[data["prod_year"] < 1991].shape
(80, 18)
Bice izbrisano samo 86 redova, sto je zanemarljiv broj ali moze da utice na konacne predikcije.
data = data[data["prod_year"] > 1989]
plt.figure(figsize=(15,7))
sns.histplot(binwidth=0.5, x="prod_year", hue="fuel", data=data, stat="count", multiple="stack")
<AxesSubplot:xlabel='prod_year', ylabel='Count'>
Ono sto je i logicno bilo pretpostaviti, godinama se menja procenat vrste goriva u automobilima, pa tako hibridi pocinju da ostvaruju uticaj tek od 2006-2007 godine. Procenat benzinaca je najveci u svim godinama dok se nakon 2015 dizel automobili skoro pa gube
plt.figure(figsize=(15,7))
plt.title('Godina proizvodnje i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('prod_year')['price'].mean().plot.bar()
plt.show()
Trend porasta cene sa novijim vozilima je aktuelan i kao sto je i za ocekivati najnovija vozila imaju najvise cene.
Postoji nekoliko odstupanja kao na primer 2018. godiste ima vecu cenu od 2019. ali to moze znaciti da za 2018. imamo luksuznije automobile nego u narednoj.
plt.figure(figsize=(15,7))
plt.title('Karoserija i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('category')['price'].mean().plot.bar()
<AxesSubplot:title={'center':'Karoserija i cena'}, xlabel='category', ylabel='Cena'>
Svaka karoserija imaju drugaciju srednju vrednost, sto je i ocekaivano jer su luksuzniji automobili uglavnom u kategorijama poput kabriolet ili dzip.
Sa druge strane imamo pickup koji ima najvecu prosecnu vrednost, sto je donekle neocekivano pa mozemo da probamo da otkrijemo o cemu se radi.
data[data.category == 'Pickup'].shape
(47, 18)
data[data.category == 'Pickup'].prod_year.value_counts()
2012 5 2010 4 2019 4 2013 4 2008 3 2017 3 2018 3 2011 3 2005 2 2007 2 1998 2 2006 2 2004 1 2020 1 1997 1 1990 1 2016 1 2015 1 1999 1 2014 1 1996 1 2009 1 Name: prod_year, dtype: int64
Kako ovde imamo uglavnom novija vozila a videli smo da godina proizvodnje utice na cenu, mozemo zakljuciti da cenu ove kategorije odredjuje godina proizvodnje vecine pickup vozila.
plt.figure(figsize=(15,7))
plt.title('Broj cilindara i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('cylinders')['price'].mean().plot.bar()
<AxesSubplot:title={'center':'Broj cilindara i cena'}, xlabel='cylinders', ylabel='Cena'>
Broj cilindara odredjuje cenu ali ne direktno, pa tako utice i broj vozila u skupu sa tim brojem cilindara na cenu.
plt.figure(figsize=(15,7))
plt.title('Vrsta goriva i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('fuel')['price'].mean().plot.bar()
plt.show()
Ovde vidimo da dizel i elektricna vozila imaju najvecu cenu, dok vozila sa CNG imaju najmanju.
Kod elektricnih vozila, godiste utice na cenu kao sto smo videli jer su to uglavnom nova vozila ali i su to takodje skupoceni modeli u svetu automobila dok dizel vozila cine vecinu u novijim automobilima u skupu.
plt.figure(figsize=(15,7))
plt.title('Broj vrata i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('doors')['price'].mean().plot.bar()
plt.show()
data[data.doors == ">5"]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 171 | 45782173 | 1300 | 0 | AUDI | 50 | 2018 | Coupe | Yes | Petrol | 0.5 | 4000 | 1.0 | Tiptronic | Rear | >5 | Right-hand drive | Blue | 0 |
| 276 | 44810053 | 20385 | 738 | CHEVROLET | Cruze | 2017 | Sedan | No | Petrol | 1.4 | 42000 | 4.0 | Tiptronic | Front | >5 | Left wheel | Black | 12 |
| 678 | 45800055 | 7213 | 0 | BMW | 525 | 1998 | Sedan | No | Petrol | 2.5 | 100000 | 6.0 | Manual | Rear | >5 | Left wheel | Silver | 6 |
| 829 | 45766759 | 30000 | 0 | NISSAN | X-Trail | 2018 | Pickup | Yes | Petrol | 2.5 | 18794 | 12.0 | Automatic | 4x4 | >5 | Left wheel | Black | 12 |
| 870 | 45788787 | 19757 | 810 | HYUNDAI | Elantra | 2016 | Sedan | No | Petrol | 1.8 | 113600 | 4.0 | Tiptronic | Front | >5 | Left wheel | Grey | 6 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 18795 | 45788558 | 10976 | 0 | TOYOTA | ISIS | 2007 | Minivan | Yes | Petrol | 2.0 | 1000 | 4.0 | Automatic | Front | >5 | Right-hand drive | White | 12 |
| 18806 | 44839699 | 11917 | 0 | FORD | Escape | 2007 | Jeep | Yes | Hybrid | 2.3 | 197000 | 4.0 | Automatic | 4x4 | >5 | Left wheel | Black | 8 |
| 19085 | 45794339 | 97219 | 1079 | LEXUS | NX 300 | 2018 | Jeep | Yes | Petrol | 2.0 | 25600 | 4.0 | Tiptronic | Front | >5 | Left wheel | White | 7 |
| 19094 | 45804509 | 11290 | 0 | FORD | Transit | 2000 | Goods wagon | No | Diesel | 2.5 | 270000 | 4.0 | Manual | Rear | >5 | Left wheel | Orange | 1 |
| 19118 | 45738530 | 23834 | 0 | TOYOTA | Alphard | 2006 | Minivan | No | LPG | 3.0 | 149000 | 6.0 | Automatic | 4x4 | >5 | Left wheel | Silver | 6 |
115 rows × 18 columns
Odnos cena izmedju automobila sa 2-3 vrata i 4-5 vrata je priblizan, ali ipak ona sa 4-5 imaju blago vecu cenu. Automobila sa vise od 5 vrata ima malo u skupu sto je prikazano i oni sadrze nekoliko automobila sa velikim cenama koje uticu na srednju vrednost.
plt.figure(figsize=(15,7))
plt.title('Kozni interijer i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('leather')['price'].mean().plot.bar()
plt.show()
Ovde vidimo da kozni interijer ima uticaj, oni automobili koji imaju kozni interijer imaju i vecu cenu jer se kozni interijer smatra skupocenijim.
plt.figure(figsize=(15,7))
plt.title('Proizvodjac i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('manufacturer')['price'].mean().plot.bar()
plt.show()
Oni proizvodjaci koji vaze za luksuznije ili imaju sportske modele imaju vece cene, kao sto je i prikazano na slici iznad. Lambordzini ima daleko skuplje automobile od ostalih, za njim sledi Bentli, Ferari, Porse koji upravo vaze za proizvodjace koji su pomenuti.
plt.figure(figsize = (15,7))
sns.heatmap(data.corr(), annot = True)
plt.title("Korelacija")
plt.show()
Najveci koeficijent korelacije imaju broj cilindara i zapermina motora, dok cena najveci koeficijent ima sa godinom proizvodnje kao sto je i primeceno na grafikonima.
Feature engineering je vazan deo procesa, kako bi se dobili sto bolji rezultati modela. To je proces selekcije, transformacije i manipulacije postojecim feature-ima za kreiranje novih i bolje resavanje problema koje ce dovesti do poboljsanih performansi modela i boljih predikcija.
Prvi feature kojim se treba pozabaviti jeste cena vozila prema kategorijama, razlikujemo one karoserije sa vecom i manjom cenom od 22000, ta cena je uzeta nakon razmatranja vizuelizacije
mean_price_category = data[['category', 'price']].groupby('category', as_index = False).mean()
normal_price = []
high_price = []
for index in range(len(mean_price_category)):
if mean_price_category.iloc[index, 1] <= 22000:
normal_price.append(mean_price_category.iloc[index, 0])
else:
high_price.append(mean_price_category.iloc[index, 0])
print('Kategorije sa cenom ispod 20000$: ', normal_price)
print('Kategorije sa cenom iznad 20000$: ', high_price)
Kategorije sa cenom ispod 20000$: ['Goods wagon', 'Hatchback', 'Microbus', 'Minivan', 'Sedan'] Kategorije sa cenom iznad 20000$: ['Cabriolet', 'Coupe', 'Jeep', 'Limousine', 'Pickup', 'Universal']
category_column = data['category']
category_price_data = []
for value in category_column:
if value in normal_price:
category_price_data.append(1)
else:
category_price_data.append(2)
data['category_price'] = category_price_data
data.head()
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 45654403 | 13328 | 1399 | LEXUS | RX 450 | 2010 | Jeep | Yes | Hybrid | 3.5 | 186005 | 6.0 | Automatic | 4x4 | 4-5 | Left wheel | Silver | 12 | 2 |
| 1 | 44731507 | 16621 | 1018 | CHEVROLET | Equinox | 2011 | Jeep | No | Petrol | 3.0 | 192000 | 6.0 | Tiptronic | 4x4 | 4-5 | Left wheel | Black | 8 | 2 |
| 2 | 45774419 | 8467 | 0 | HONDA | FIT | 2006 | Hatchback | No | Petrol | 1.3 | 200000 | 4.0 | Variator | Front | 4-5 | Right-hand drive | Black | 2 | 1 |
| 3 | 45769185 | 3607 | 862 | FORD | Escape | 2011 | Jeep | Yes | Hybrid | 2.5 | 168966 | 4.0 | Automatic | 4x4 | 4-5 | Left wheel | White | 0 | 2 |
| 4 | 45809263 | 11726 | 446 | HONDA | FIT | 2014 | Hatchback | Yes | Petrol | 1.3 | 91901 | 4.0 | Automatic | Front | 4-5 | Left wheel | Silver | 4 | 1 |
Sledeci feature je godina proizvodnje koju cemo da transformisemo u broj godina starosti tako sto ce biti oduzeta godina proizvodnje od trenutne godine.
year_data = data['prod_year']
age_data = []
for value in year_data:
age_data.append(2022 - value)
data['age'] = age_data
len(set(age_data))
31
Na kraju ce kolona tip goriva biti izmenjena, da ne bi model bio zbunjen smanjicemo vrste goriva na neke uobicajene tipove koji su zastupljeniji od ostalih.
data.fuel.value_counts()
Petrol 9083 Diesel 3808 Hybrid 2926 LPG 868 CNG 455 Plug-in Hybrid 85 Hydrogen 1 Name: fuel, dtype: int64
fuel_type_data = data['fuel']
new_fuel_type_data = []
for value in fuel_type_data:
if value in {'LPG', 'Hydrogen', 'Plug-in Hybrid', 'CNG'}:
new_fuel_type_data.append('Other')
else:
new_fuel_type_data.append(value)
set(new_fuel_type_data)
{'Diesel', 'Hybrid', 'Other', 'Petrol'}
Da bi podaci bili razumljivi modelu, potrebno je enkodirati promenljive to jest umesto vrednosti poput u koloni leather Yes ce biti 1 a No 0.
Sve kategorijske vrednosti bice zamenjene numerickim, gde ce jedan broj predstavljati jednu vrednost.
Pre toga, bitno je odabrati samo korisne kolone
new_data = data[["ID","price","manufacturer","model","age","category_price","leather","fuel","mileage","gearbox","drivewheels","doors","wheel","airbags"]]
dummy_data = pd.get_dummies(new_data, columns=["manufacturer","model","leather","fuel","drivewheels","wheel","doors", "category_price","gearbox"], drop_first=True, dtype='uint8')
new_data.reset_index(drop=True)
| ID | price | manufacturer | model | age | category_price | leather | fuel | mileage | gearbox | drivewheels | doors | wheel | airbags | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 45654403 | 13328 | LEXUS | RX 450 | 12 | 2 | Yes | Hybrid | 186005 | Automatic | 4x4 | 4-5 | Left wheel | 12 |
| 1 | 44731507 | 16621 | CHEVROLET | Equinox | 11 | 2 | No | Petrol | 192000 | Tiptronic | 4x4 | 4-5 | Left wheel | 8 |
| 2 | 45774419 | 8467 | HONDA | FIT | 16 | 1 | No | Petrol | 200000 | Variator | Front | 4-5 | Right-hand drive | 2 |
| 3 | 45769185 | 3607 | FORD | Escape | 11 | 2 | Yes | Hybrid | 168966 | Automatic | 4x4 | 4-5 | Left wheel | 0 |
| 4 | 45809263 | 11726 | HONDA | FIT | 8 | 1 | Yes | Petrol | 91901 | Automatic | Front | 4-5 | Left wheel | 4 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 17221 | 45772306 | 5802 | MERCEDES-BENZ | E 350 | 9 | 1 | Yes | Diesel | 107800 | Automatic | Rear | 4-5 | Left wheel | 12 |
| 17222 | 45798355 | 8467 | MERCEDES-BENZ | CLK 200 | 23 | 2 | Yes | CNG | 300000 | Manual | Rear | 2-3 | Left wheel | 5 |
| 17223 | 45778856 | 15681 | HYUNDAI | Sonata | 11 | 1 | Yes | Petrol | 161600 | Tiptronic | Front | 4-5 | Left wheel | 8 |
| 17224 | 45804997 | 26108 | HYUNDAI | Tucson | 12 | 2 | Yes | Diesel | 116365 | Automatic | Front | 4-5 | Left wheel | 4 |
| 17225 | 45793526 | 5331 | CHEVROLET | Captiva | 15 | 2 | Yes | Diesel | 51258 | Automatic | Front | 4-5 | Left wheel | 4 |
17226 rows × 14 columns
X predstavlja skup koji ne sadrzi cenu kako bi model mogao da uci, y prestavlja labele.
X=dummy_data.drop(columns='price')
y=dummy_data['price']
X_train , X_test , y_train , y_test = train_test_split(X,y,random_state=1,test_size=0.2)
X_train.head()
| ID | age | mileage | airbags | manufacturer_ALFA ROMEO | manufacturer_ASTON MARTIN | manufacturer_AUDI | manufacturer_BENTLEY | manufacturer_BMW | manufacturer_BUICK | ... | fuel_Plug-in Hybrid | drivewheels_Front | drivewheels_Rear | wheel_Right-hand drive | doors_4-5 | doors_>5 | category_price_2 | gearbox_Manual | gearbox_Tiptronic | gearbox_Variator | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 7050 | 45656442 | 9 | 137802 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ... | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| 6467 | 45438005 | 7 | 79000 | 8 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
| 10683 | 45647914 | 6 | 448982 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| 4846 | 45809752 | 9 | 86262 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 10986 | 45730592 | 13 | 56629 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
5 rows × 1624 columns
X_test.head()
| ID | age | mileage | airbags | manufacturer_ALFA ROMEO | manufacturer_ASTON MARTIN | manufacturer_AUDI | manufacturer_BENTLEY | manufacturer_BMW | manufacturer_BUICK | ... | fuel_Plug-in Hybrid | drivewheels_Front | drivewheels_Rear | wheel_Right-hand drive | doors_4-5 | doors_>5 | category_price_2 | gearbox_Manual | gearbox_Tiptronic | gearbox_Variator | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5673 | 45802007 | 11 | 135746 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
| 14269 | 45791372 | 16 | 6000 | 10 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
| 17826 | 45798064 | 12 | 100403 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 2334 | 45776665 | 25 | 155000 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 |
| 18010 | 45662052 | 12 | 187312 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 rows × 1624 columns
Ovde smo podelili promenljive na skup za trening i skup za test. Ideja je da se nakon treniranja, ponasanje modela proveri nad podacima sa kojima do sada nije upoznat.
Sada kada smo pripremili podatke, mozemo primeniti modele masinskog ucenja.
Modeli koje cemo primeniti su Linarna regresija i Random Forest
Prosta regresija je regresioni metod koji razmatra vezu izmedju jedne zavisno promenljive Y i jedne nezavisno promenljive X.
Neki od parametara:
fit_interceptbool, default=True Ovim parametrom se odredjuje da li da se racuna intercept u modelu.
n_jobsint, default=None Broj "jobova" koje ce se koristiti za izracunavanje
Random forest je specijalizovan nacin klasifikacije koji funkcioniše na principu stabla odluke. Stablo odluke (engl. decision tree) je
stuktura nalik binarnim stablima, gde svaki cvor predstavlja test na odredjenu karakteristiku, dok listovi stabla predstavljaju konacnu odluku stabla.
Random forest se sastoji od više razlicitih stabala odluka koji nezavisno jedni od drugih klasifikuju test primer. Konacna odluka random foresta se
formira kada se usrednje odlucene vrednosti svih stabala, i uzorak se svrstava u onu klasu za koju je najviše stabala glasalo.
Neki od parametara modela:
n_estimatorsint, default=100
Broj stabala u "šumi"
criterion{“squared_error”, “absolute_error”, “poisson”}, default=”squared_error”
max_depthint, default=None Maksimalna dubina stabla.
lr = LinearRegression()
lr.fit(X_train, y_train)
LinearRegression()
reg_predict_train = lr.predict(X_train)
reg_predict_test = lr.predict(X_test)
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_train, reg_predict_train),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_train, reg_predict_train),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_train, reg_predict_train)),2))
Mean Absolute Error: 7474.89 Mean Squared Error: 134037937.8 Root Mean Squared Error: 11577.48
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_test, reg_predict_test),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_test, reg_predict_test),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_test, reg_predict_test)),2))
Mean Absolute Error: 187874.81 Mean Squared Error: 4346331103397.76 Root Mean Squared Error: 2084785.63
reg_predict2 = lr.predict(X_test)
rf_reg = RandomForestRegressor(n_estimators=20, random_state=0)
rf_reg.fit(X_train, y_train)
RandomForestRegressor(n_estimators=20, random_state=0)
rf_pred_test = rf_reg.predict(X_test)
rf_pred_train = rf_reg.predict(X_train)
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_train, rf_pred_train),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_train, rf_pred_train),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_train, rf_pred_train)),2))
Mean Absolute Error: 1608.07 Mean Squared Error: 12999295.59 Root Mean Squared Error: 3605.45
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_test, rf_pred_test),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_test, rf_pred_test),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_test, rf_pred_test)),2))
Mean Absolute Error: 4497.18 Mean Squared Error: 134107488.56 Root Mean Squared Error: 11580.48
Ovde su uradjene predikcije nad test i train skupom, iz prilozenog mozemo da vidimo da bolje rezultate imaju predikcije nad train skupom ali je praksa da se predikcije rade nad testnim skupom kako bi se videlo ponasanje modela nad podacima koje do sada nije video.
U celiji ispod su prikazani rezultati predikcije cene za pojedine automobile
Da bi prikazali nekoliko rezultata kako izgledaju stvarni podaci i ono sto su modeli predvideli, moramo prvo pronaci nekoliko automobila iz y_test i predstaviti ih sa podacima koji nisu dummy i onda uporediti prave i prediktovane vrednosti
test_car_id = list(X_test["ID"].head(10))
test_car_id
[45802007, 45791372, 45798064, 45776665, 45662052, 45776995, 45790231, 45794822, 45700887, 45726679]
data[data['ID'] == 45802007]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5673 | 45802007 | 21395 | 1266 | HYUNDAI | Genesis | 2011 | Coupe | Yes | Petrol | 3.8 | 135746 | 4.0 | Automatic | Front | 4-5 | Left wheel | Grey | 4 | 2 | 11 |
rf_pred_test[0]
20684.8
reg_predict_test[0]
21072.942425985355
Kako znamo pozicije u skupovima podataka na osnovu ID kolone nalazimo automobil u izvornom skupu i na osnovu toga uporedjujemo vrednosti. Random Forest je predvideo nizu cenu za 711 dolara dok je linearna regresija omasila za 320. Iz ovog jednog primera mozemo da kazemo da je Random Forest za nijansu losiji posao uradio. Da ne bismo zakljucke bazirali samo na jednom uzorku, ponovicemo pristup za jos nekoliko automobila i videti da li su slicni rezultati.
data[data['ID'] == 45791372]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 14269 | 45791372 | 18189 | 0 | LINCOLN | Navigator | 2006 | Jeep | Yes | Petrol | 5.4 | 6000 | 8.0 | Tiptronic | 4x4 | 4-5 | Left wheel | White | 10 | 2 | 16 |
rf_pred_test[1]
17467.85
reg_predict_test[1]
34472.19573950488
Kod ovog automobila, Random Forest je dao solidno dobar rezultat dok je linearna regresija neverovatno mnogo omasila.
data[data['ID'] == 45798064]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 17826 | 45798064 | 14069 | 687 | HYUNDAI | Elantra | 2010 | Sedan | Yes | Petrol | 1.6 | 100403 | 4.0 | Automatic | Front | 4-5 | Left wheel | White | 4 | 1 | 12 |
rf_pred_test[2]
13949.55
reg_predict_test[2]
10245.51498335367
Ovde imamo slican slucaj, RF je omasio za samo 100 dolara dok je LR za skoro 4000
data[data['ID'] == 45662052]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 18010 | 45662052 | 1803 | 574 | HONDA | Insight | 2010 | Hatchback | Yes | Hybrid | 1.3 | 187312 | 4.0 | Automatic | Front | 4-5 | Left wheel | Blue | 0 | 1 | 12 |
rf_pred_test[4]
1709.05
reg_predict_test[4]
4864.438932470046
Isto i ovde
data[data['ID'] == 45790231]
| ID | price | levy | manufacturer | model | prod_year | category | leather | fuel | engine_volume | mileage | cylinders | gearbox | drivewheels | doors | wheel | color | airbags | category_price | age | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3106 | 45790231 | 21639 | 650 | CHEVROLET | Cruze | 2016 | Sedan | Yes | Petrol | 1.4 | 99200 | 4.0 | Tiptronic | Front | 4-5 | Left wheel | Black | 10 | 1 | 6 |
rf_pred_test[6]
22322.7
reg_predict_test[6]
22920.375845366623
Ovde je za razliku od ostalih slucajeva LR dala za nijansu losiji rezultat od RF, ali iz nekoliko nasumicno odabranih primera mozemo da zakljucimo da Random Forest daje zadovoljavajuce rezultate predikcija cene za automobile dok je Linearna regresija u nekim slucajevima dosta losija.